#include <iostream>
#include <sys/sem.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <unistd.h>

class Csemp
{
private:
    // 用于信号量操作的共同体
    union semun
    {
        int val;
        struct semid_ds *buf;
        unsigned short *arry;
    };

    // 信号量id（描述符）
    int m_semid;

    /*
        如果把m_sem_flag设置为SEM_UNDO，操作系统将跟踪进程对信号量的修改情况
        在全部修改过信号量的进程(正常或异常)终止后，操作系统将把信号量恢复
        为初始值(像撤销了全部进程对信号的操作)
        如果信号量用于互斥锁，设置为SEM_UNDO
        如果信号量用于生产消费者模型，设置为0
    */
    short m_sem_flag;

    // 禁止拷贝构造函数
    Csemp(const Csemp &) = delete;

    // 禁止赋值函数
    Csemp &operator=(const Csemp &) = delete;
    
public:
    Csemp():m_semid(-1){}

    /*
        如果信号量已存在，获取信号量；如果信号量不存在，则创建，并初始化为value
        如果用于互斥锁，value=1，sem_flag=SEM_UNDO
        如果用于生产消费者模型，value=0,sem_flag=0
    */
    bool init(key_t key, unsigned short value=1, short sem_flag=SEM_UNDO);
    
    // 信号量的P操作，如果信号量的值是0，将阻塞等待，直到信号量的值大于0
    bool wait(short sem_op=-1);

    // 信号量的V操作
    bool post(short sem_op=1);

    // 获取信号量的值，成功返回信号量的值，失败返回-1
    int getvalue();

    // 销毁信号量
    bool destroy();
    ~Csemp();
};




